﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Macro
{
    public delegate void keyboardCallback(ushort vkCode, bool keyDown, bool keyUp);
    public delegate void mouseCallback(int x, int y, bool lbuttonDown, bool lbuttonUp, bool rbuttonDown, bool rbuttonUp, bool mouseMove);

    public partial class Form1 : Form
    {
        private List<Command> commands;

        public Form1()
        {
            InitializeComponent();
            commands = new List<Command>();

            recordingOn = false;
            button2.Enabled = false;

            globalKeyboardHook.setKeyboardCallback(addKeyboardCommand);
            globalMouseHook.setMouseCallback(addMouseCommand);
        }
        ~Form1()
        {
            globalKeyboardHook.stop();
            globalMouseHook.stop();
        }

        private void addKeyboardCommand(ushort vkCode, bool keyDown, bool keyUp)
        {
            double wt = new TimeSpan(DateTime.Now.Ticks - recordingStartTicks).TotalSeconds;
            Command c = new keyboardCommand(wt, vkCode, keyDown, keyUp);
            addCommand(c);
        }
        private void addMouseCommand(int x, int y, bool lbuttonDown, bool lbuttonUp, bool rbuttonDown, bool rbuttonUp, bool mouseMove)
        {
            int width = Screen.PrimaryScreen.Bounds.Width;
            int height = Screen.PrimaryScreen.Bounds.Height;

            //see http://msdn.microsoft.com/en-us/library/ms646273.aspx#2
            int absx = (int)Math.Ceiling(x * 65536.0 / width);
            int absy = (int)Math.Ceiling(y * 65536.0 / height);

            double wt = new TimeSpan(DateTime.Now.Ticks - recordingStartTicks).TotalSeconds;
            Command c = new mouseCommand(wt, absx, absy, lbuttonDown, lbuttonUp, rbuttonDown, rbuttonUp, mouseMove);
            addCommand(c);
        }
        private void addCommand(Command c)
        {
            commands.Add(c);

            int n = dataGridView1.Rows.Add();
            dataGridView1.Rows[n].Cells[0].Value = c.getWaitingTime();
            dataGridView1.Rows[n].Cells[1].Value = c.getDescription();
        }
        private void replayCommands()
        {
            double delta;
            long playbackStartTicks = DateTime.Now.Ticks;

            for (int i = 0; i < commands.Count; i++)
            {
                //spin and wait
                do
                {
                    delta = new TimeSpan(DateTime.Now.Ticks - playbackStartTicks).TotalSeconds;
                }
                while (delta < commands[i].getWaitingTime());

                commands[i].execute();
            }
        }

        private bool recordingOn;
        private long recordingStartTicks;
        private void button1_Click(object sender, EventArgs e)
        {
            recordingOn = !recordingOn;

            if (recordingOn)
            {
                //clear previous commands. This calls the RowsRemoved event for all rows.
                //This event will remove the corresponding entry from the commands list.
                dataGridView1.Rows.Clear();
                recordingStartTicks = DateTime.Now.Ticks;

                button1.Text = "Stop Recording";
                button2.Enabled = false;

                globalKeyboardHook.start();
                globalMouseHook.start();
            }
            else
            {
                button1.Text = "Start Recording";
                button2.Enabled = true;

                globalKeyboardHook.stop();
                globalMouseHook.stop();
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            button2.Enabled = false;

            for (int i = 0; i < (int)numericUpDown1.Value; i++)
            {
                replayCommands();
            }

            button1.Enabled = true;
            button2.Enabled = true;
        }

        private void dataGridView1_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            for (int i = (e.RowIndex + e.RowCount - 1); i >= e.RowIndex; i--)
            {
                commands.RemoveAt(i);
            }
        }
    }
}
